﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Text;
using T.ServiceComponent.Monitor.Client;
using System.Threading;
using T.ServiceFramework.Spi;
using System.Linq;
using System.Threading.Tasks;
using T.ServiceComponent.Kernel.Service;
using ServiceType = T.ServiceFramework.Spi.ServiceType;

namespace T.SF.Console
{
    public class HostController
    {
        private static HostController current = null;
        private static readonly object lckobject = new object();

        public static HostController Current
        {
            get
            {
                if (current == null)
                {
                    lock (lckobject)
                    {
                        if (current == null)
                            current = new HostController();
                    }
                }
                return current;
            }
        }

        private HostController()
        {
            syncobj = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
            showInfos = new ConcurrentQueue<string>();
        }

        #region LoadService
        private bool isShowInvokeLog = false;
        private System.Threading.Timer logShowTimer;
        private ConcurrentQueue<string> showInfos = null;
        private readonly ReaderWriterLockSlim syncobj;

        public event RestartEventHandler OnRestart;

        /// <summary>
        /// 加载 配置
        /// </summary>
        /// <param name="isRefresh">是否重新加载</param>
        private void StartService(string port)
        {
            this.Status = HostStatus.Starting;
            WriteLine("Initializing...");

            SetShowInvokeLogState(isShowInvokeLog);

            WriteLine("Starting...");

            SetContext(port);
            ProviderController.StartService();

            this.Status = HostStatus.Runing;

            ReportRestartAndHeartbeat();
        }

        private static void SetContext(string port)
        {
            if (SFContext.Host != null)
            {
                return;
            }
            var host = ClusterService.GetMyHostInfo();

            SFContext.Host = host;
           
            //增加进程全局上下文信息，以便基础组件埋点上报
            if (host != null)
            {
                EnvironmentContext.SetCommonMonitorData("HostID", host.ID);
                EnvironmentContext.SetCommonMonitorData("ClusterID", host.ClusterID);
                T.ServiceComponent.Session.Service.AppContext.Current.HostID = host.ID;
            }

            if (string.IsNullOrEmpty(port) == false)
            {
                if (port.StartsWith("HSFPort:", StringComparison.OrdinalIgnoreCase))
                {
                    var hsf = SFContext.Host.BindingList.FirstOrDefault(x => x.ServiceType == ServiceType.HSF);
                    if (hsf == null)
                        SFContext.Host.BindingList.Add(new Binding() { IP = "127.0.0.1", Port = Convert.ToInt32(port.ToUpper().Replace("HSFPORT:", "")), ServiceType = ServiceType.HSF });
                    else
                    {
                        hsf.Port = Convert.ToInt32(port.ToUpper().Replace("HSFPORT:", ""));
                    }
                }
                else if (port.StartsWith("SG:", StringComparison.OrdinalIgnoreCase))
                {
                    var sg = SFContext.Host.BindingList.FirstOrDefault(x => x.ServiceType == ServiceType.HSF);
                    if (sg == null)
                        SFContext.Host.BindingList.Add(new Binding() { IP = "127.0.0.1", Port = Convert.ToInt32(port.ToUpper().Replace("SGPORT:", "")), ServiceType = ServiceType.SG });
                    else
                    {
                        sg.Port = Convert.ToInt32(port.ToUpper().Replace("SGPORT:", ""));
                    }
                }

            }

            if (host == null)
                throw new Exception("Unable to get the current AppHost identity information.");
        }

        private static Thread heartbeatThread;
        private static void ReportRestartAndHeartbeat()
        {
            MonitorProvider.ReportRestart();
            heartbeatThread = new Thread(() =>
            {
                while (true)
                {
                    MonitorProvider.ReportHeartbeat();
                    Thread.Sleep(10 * 1000);
                }
            })
            {
                IsBackground = true,
                Name = "tsf heartbeat thread"
            };
            heartbeatThread.Start();
        }

        /// <summary>
        /// 输出
        /// </summary>
        /// <param name="message">消息文本</param>
        private void WriteLine(string message)
        {
            System.Console.WriteLine(string.Format("{0}: {1}", DateTime.Now.ToString(), message));
        }


        private void HighPerfWriteLine(string message, bool addTime = true)
        {
            if (addTime)
                showInfos.Enqueue(string.Format("{0}: {1}", DateTime.Now.ToString(), message));
            else
                showInfos.Enqueue(message);
        }

        private void HighPerfShowLog()
        {
            StringBuilder sb = new StringBuilder(500);
            string log = string.Empty;
            while (showInfos.TryDequeue(out log))
            {

                sb.AppendLine(log);
            }

            if (sb.Length <= 0)
                return;

            System.Console.Write(sb.ToString());
        }


        private void DisplayError(Exception e)
        {
            if (e != null)
            {
                HighPerfWriteLine(e.Message);
                HighPerfWriteLine(e.StackTrace);

                if (e.InnerException != null)
                    DisplayError(e.InnerException);
            }
        }
        #endregion

        #region Public

        public void RaiseRestartEvent(string reason)
        {
            if (OnRestart != null)
                OnRestart(reason);
        }

        public void Start(string port)
        {
            if (this.logShowTimer == null)
            {
                this.logShowTimer = new System.Threading.Timer((ss) =>
                {
                    syncobj.EnterWriteLock();
                    try
                    {
                        HighPerfShowLog();
                    }
                    catch
                    {
                    }
                    finally
                    {
                        syncobj.ExitWriteLock();
                    }
                }, null, 1000 * 10, 1000 * 10);
            }

            //加载Agent配置
            StartService(port);
        }
        public void SetShowInvokeLogState(bool isShow)
        {
            isShowInvokeLog = isShow;
        }

        public void DisposeService()
        {
            try
            {
                ConsoleService.Show("Service terminated!", LogShowType.FailInfo);

                ProviderController.StopService();
                MonitorClient.Close();
            }
            catch
            {
            }
        }

        #endregion

        #region Status Management
        private HostStatus status;
        /// <summary>
        /// Agent状态
        /// </summary>
        public HostStatus Status
        {
            get
            {
                return status;
            }
            set
            {
                status = value;
                switch (status)
                {
                    case HostStatus.Runing:
                        SetRunStatus();
                        break;
                    case HostStatus.Starting:
                        SetStartingStatus();
                        break;
                    case HostStatus.Shutdown:
                    case HostStatus.Error:
                    default:
                        SetShutdownStatus();
                        break;

                    case HostStatus.FindNewVersion:
                        break;
                }
            }
        }
        private void SetRunStatus()
        {
            WriteLine("Host State: Running.");
        }

        private void SetShutdownStatus()
        {
            WriteLine("Host State: Stopped.");
        }

        private void SetStartingStatus()
        {
            WriteLine("Host State: Loading...");
        }

        internal void ShowLogInfo(LogInfo logInfo)
        {
            if (logInfo == null)
                return;
            if (logInfo.Level == LogLevel.Fatal || logInfo.Level == LogLevel.Error)
            {
                //HighPerfWriteLine(logInfo.Message);
                ConsoleService.Show(logInfo.Message, LogShowType.FailInfo);
                if (string.IsNullOrEmpty(logInfo.ErrorStack) == false)
                    ConsoleService.Show(logInfo.ErrorStack, LogShowType.GeneralInfo);
            }

            if (isShowInvokeLog && (logInfo.Level == LogLevel.Warnning || logInfo.Level == LogLevel.Trace))
            {
                HighPerfWriteLine(logInfo.Message);
                if (string.IsNullOrEmpty(logInfo.ErrorStack) == false)
                    HighPerfWriteLine(logInfo.ErrorStack);
            }
        }
        #endregion
    }

    public enum HostStatus
    {
        /// <summary>
        /// 启动
        /// </summary>
        Starting,

        /// <summary>
        /// 运行
        /// </summary>
        Runing,

        /// <summary>
        /// 关闭
        /// </summary>
        Shutdown,

        /// <summary>
        /// 出错
        /// </summary>
        Error,

        /// <summary>
        /// 发现新版本
        /// </summary>
        FindNewVersion
    }
}
